
#include "MasterThread.h"

#include <QSerialPort>
#include <QTime>

MasterThread::MasterThread(QObject* parent) :
	QThread(parent)
{
}

//! [0]
MasterThread::~MasterThread()
{
	m_mutex.lock();
	m_quit = true;
	m_cond.wakeOne();
	m_mutex.unlock();
	wait();
}
//! [0]

//! [1] //! [2]
void MasterThread::transaction(const QString& portName, int waitTimeout, const QString& request)
{
	//! [1]
	const QMutexLocker locker(&m_mutex);
	m_portName = portName;
	m_waitTimeout = waitTimeout;
	m_request = request;
	//! [3]
	if (!isRunning())
		start();
	else
		m_cond.wakeOne();
}
//! [2] //! [3]

//! [4]
void MasterThread::run()
{
	bool currentPortNameChanged = false;

	m_mutex.lock();
	//! [4] //! [5]
	QString currentPortName;
	if (currentPortName != m_portName) {
		currentPortName = m_portName;
		currentPortNameChanged = true;
	}

	int currentWaitTimeout = m_waitTimeout;
	QString currentRequest = m_request;
	m_mutex.unlock();
	//! [5] //! [6]
	QSerialPort serial;

	if (currentPortName.isEmpty()) {
		emit error(tr("No port name specified"));
		return;
	}

	while (!m_quit) {
		//![6] //! [7]
		if (currentPortNameChanged) {
			serial.close();
			serial.setPortName(currentPortName);

			if (!serial.open(QIODevice::ReadWrite)) {
				emit error(tr("Can't open %1, error code %2")
					.arg(m_portName).arg(serial.error()));
				return;
			}
		}
		//! [7] //! [8]
				// write request
		const QByteArray requestData = currentRequest.toUtf8();
		serial.write(requestData);
		if (serial.waitForBytesWritten(m_waitTimeout)) {
			//! [8] //! [10]
						// read response
			if (serial.waitForReadyRead(currentWaitTimeout)) {
				QByteArray responseData = serial.readAll();
				while (serial.waitForReadyRead(10))
					responseData += serial.readAll();

				const QString response = QString::fromUtf8(responseData);
				//! [12]
				emit this->response(response);
				//! [10] //! [11] //! [12]
			}
			else {
				emit timeout(tr("Wait read response timeout %1")
					.arg(QTime::currentTime().toString()));
			}
			//! [9] //! [11]
		}
		else {
			emit timeout(tr("Wait write request timeout %1")
				.arg(QTime::currentTime().toString()));
		}
		//! [9]  //! [13]
		m_mutex.lock();
		m_cond.wait(&m_mutex);
		if (currentPortName != m_portName) {
			currentPortName = m_portName;
			currentPortNameChanged = true;
		}
		else {
			currentPortNameChanged = false;
		}
		currentWaitTimeout = m_waitTimeout;
		currentRequest = m_request;
		m_mutex.unlock();
	}
	//! [13]
}
